/**
 * 文件名：@WebContext.java <br/>
 * 包名：cn.efunbox.afw.web.mvc.context <br/>
 * 项目名：afw-mvc-web <br/>
 * @author xtwin <br/>
 */
package cn.efunbox.afw.web.mvc.context;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;

import cn.efunbox.afw.core.mvc.context.RichMapContext;
import cn.efunbox.afw.core.mvc.session.SessionUpdatable;
import cn.efunbox.afw.web.util.AfwWebConstant;

/**
 * 类名：WebContext  <br />
 *
 * 功能：基于web环境（基于servlet）的上下文实现
 *
 * @author xtwin <br />
 * 创建时间：2015年12月1日 下午2:26:34  <br />
 * @version 2015年12月1日
 */
public class WebContext extends RichMapContext implements SessionUpdatable {
	
	// 日志记录器
	private static final Log logger = LogFactory.getLog(WebContext.class);
	
	// http请求对象
	private HttpServletRequest request;
	
	// 标识是否已经执行过初始化操作
	private boolean inited;
	
	// 会话提供者
	//private SessionProvider sessionProvider;
	
	/**
	 * 构造方法
	 */
	public WebContext(HttpServletRequest request) {
		this.request = request;
	}
	
	/**
	 * 
	 * 功能：初始化 <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2013-11-21 下午03:25:54 <br/>
	 */
	@SuppressWarnings("unchecked")
	public void init() throws Exception {
		if (inited) {
			return;
		}
		
		// 遍历请求参数到容器中
		Enumeration<String> es = request.getParameterNames();
		while (es.hasMoreElements()) {
			String name = es.nextElement();
			
			String[] values = request.getParameterValues(name);
			if (null != values && values.length > 0) {
				// 更新到数据容器
				setValue(name, values.length == 1 ? values[0] : values);
			}
		}
		
		// 处理文件上传
		if (request instanceof MultipartRequest) {
			MultipartRequest req = (MultipartRequest) request;
			
			for (Entry<String, MultipartFile> entry : req.getFileMap().entrySet()) {
				if (entry.getValue().getSize() > 0) {
					setValue(entry.getKey(), entry.getValue());
				}
				
				if (logger.isDebugEnabled()) {
					logger.debug("file : " + entry.getKey() + " - " + entry.getValue());
				}
			}
		}
		
		// 用属性里面的数据覆盖参数里面的
		es = request.getAttributeNames();
		while (es.hasMoreElements()) {
			String name = es.nextElement();
			
			// 更新到数据容器
			setValue(name, request.getAttribute(name));
		}
		
		// 将当前用户放到容器中，方便后续取值
		Object user = getUser();
		if (null != user) {
			super.setUser(user);
		}
		
		inited = true;
	}
	
	/**
	 * 
	 * 功能： <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2013-11-21 下午03:26:39 <br/>
	 */
	public byte[] getContent() {
		InputStream is = getInputStream();
		
		if (null != is) {
			int len = request.getContentLength();
			
			byte[] buffer = new byte[len];
			
			try {
				for (int i = 0; i < len;) {
					int k = is.read(buffer, i, len - i);
					
					i += k;
				}
			} catch (IOException e) {
				logger.error("stream.read.error", e);
				
				return null;
			}
			
			return buffer;
		}
		
		return null;
	}
	
	/**
	 * 
	 * 功能： <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2013-11-21 下午03:27:02 <br/>
	 */
	public InputStream getInputStream() {
		String ctype = request.getContentType();
		
		if (null != ctype && ctype.toLowerCase().startsWith("application/stream")) {
			try {
				return request.getInputStream();
			} catch (IOException e) {
				logger.error("stream.get.error", e);
			}
		}
		
		return null;
	}

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2013-11-21 下午03:25:21<br/>
	 * 
	 * @param name
	 * @param value <br/>
	 * @see com.bocsd.cpfp.common.core.context.SessionUpdateable#setSessionAttribute(java.lang.String, java.lang.Object)
	 */
	@Override
	public void setSessionAttribute(String name, Object value) {
		request.getSession().setAttribute(name, value);
		//sessionProvider.setAttribute(name, value);
	}

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2013-11-21 下午03:25:21<br/>
	 * 
	 * @param <V>
	 * @param name
	 * @return <br/>
	 * @see com.bocsd.cpfp.common.core.context.SessionUpdateable#getSessionAttribute(java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public <V> V getSessionAttribute(String name) {
		HttpSession session = request.getSession(false);
		
		if (null != session) {
			return (V) session.getAttribute(name);
		}
		
		return null;
		
		//return sessionProvider.getAttribute(name);
	}

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2013-11-21 下午05:07:32<br/>
	 * 
	 * @param name <br/>
	 * @see com.bocsd.cpfp.common.core.context.SessionUpdateable#removeSessionAttribute(java.lang.String)
	 */
	@Override
	public void removeSessionAttribute(String name) {
		HttpSession session = request.getSession(false);
		
		if (null != session) {
			session.removeAttribute(name);
		}
		
		//sessionProvider.removeAttribute(name);
	}

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2013-12-4 下午05:13:22<br/>
	 * 
	 * @return <br/>
	 * @see com.bocsd.cpfp.common.core.context.SessionUpdateable#getSessionId()
	 */
	//@Override
	public String getSessionId() {
		HttpSession session = request.getSession(false);
		
		if (null != session) {
			return session.getId();
		}
		
		return null;
		//return sessionProvider.getId();
	}

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2015-6-26 下午02:21:16<br/>
	 * 
	 * @param <T>
	 * @return <br/>
	 * @see com.bocsd.cpfp.common.core.context.Context#getUser()
	 */
	@SuppressWarnings("unchecked")
	@Override
	public <T> T getUser() {
		HttpSession session = request.getSession(false);
		
		if (null != session) {
			return (T) session.getAttribute(AfwWebConstant.KEY_IDENTITY_SESSION);
		}
		
		return super.getUser();
		
		/*T user = super.getUser();
		if (null == user) {
			user = sessionProvider.getAttribute(FWConstant.KEY_IDENTITY_SESSION);
			
			if (null != user) {
				super.setUser(user);
			}
		}
		
		return user;*/
	}

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2015-6-26 下午02:21:48<br/>
	 * 
	 * @param user <br/>
	 * @see com.bocsd.cpfp.common.core.context.Context#setUser(java.lang.Object)
	 */
	@Override
	public void setUser(Object user) {
		HttpSession session = request.getSession(false);
		
		if (user == getUser()) {
			if (null != session && null != user) {
				session.setAttribute(AfwWebConstant.KEY_IDENTITY_SESSION, user);
			}
		} else {
			if (null != session) {
				session.invalidate();
			}
			
			if (null != user) {
				session = request.getSession(true);
				
				session.setAttribute(AfwWebConstant.KEY_IDENTITY_SESSION, user);
			}
			super.setUser(user);
		}
	}
}
